/* 定义状态自动机的状态 */
const STATE = {
  INITIAL: 1,
  TAG_OPEN: 2,
  TAG_NAME: 3,
  TEXT: 4,
  TAG_END: 5,
  TAG_END_NAME: 6,
};

/**
 * @description 判断字符是否是字母
 * @param {*} char 字符
 * @returns Boolean
 */
function isAlpha(char) {
  return (char >= "a" && char <= "z") || (char >= "A" && char <= "Z");
}

export function tokenize(str) {
  console.log(str);
  /* 状态自动机的当前状态：初始状态 */
  let currentState = STATE.INITIAL;
  /* 用于缓存字符 */
  let chars = [];
  /* 用于缓存生称的 Token，并作为函数的返回值返回 */
  let tokens = [];

  /* 使用while循环开启自动机，直到模板字符串被消费尽才停止 */
  while (str) {
    console.log(str);
    /* 从模板字符串中取出一个字符 */
    const char = str[0];
    /* switch 语句匹配状态自动机的当前状态 */
    switch (currentState) {
      case STATE.INITIAL:
        if (char === "<") {
          /* 将当前状态改为标签开始状态 */
          currentState = STATE.TAG_OPEN;
          /* 消费掉字符 < */
          str = str.slice(1);
        } else if (isAlpha(char)) {
          /* 将当前状态改为文本状态 */
          currentState = STATE.TEXT;
          /* 将字母添加到缓存中 */
          chars.push(char);
          /* 消费掉字符 */
          str = str.slice(1);
        }
        break;
      case STATE.TAG_OPEN:
        if (isAlpha(char)) {
          /* 将当前状态改为标签名称状态 */
          currentState = STATE.TAG_NAME;
          /* 将当前字母添加到缓存中 */
          chars.push(char);
          /* 消费掉字符 */
          str = str.slice(1);
        } else if (char === "/") {
          /* 将当前状态改为标签结束状态 */
          currentState = STATE.TAG_END;
          /* 消费掉字符 */
          str = str.slice(1);
        }
        break;

      case STATE.TAG_NAME:
        if (isAlpha(char)) {
          /* 将当前字母添加到缓存中 */
          chars.push(char);
          /* 消费掉字符 */
          str = str.slice(1);
        } else if (char === ">") {
          /* 将当前状态改为初始状态 */
          currentState = STATE.INITIAL;
          /* 生成一个标签 Token， */
          tokens.push({ type: "tag", name: chars.join("") });
          /* 清空缓存 */
          chars.length = 0;
          /* 消费掉字符 */
          str = str.slice(1);
        }
        break;

      case STATE.TEXT:
        if (isAlpha(char)) {
          /* 将字母添加到缓存 */
          chars.push(char);
          /* 消费掉字符 */
          str = str.slice(1);
        } else if (char === "<") {
          /* 将当前状态改为标签开始状态 */
          currentState = STATE.TAG_OPEN;
          /* 生成一个文本内容的token，并添加到tokens中 */
          tokens.push({
            type: "text",
            content: chars.join(""),
          });
          /* 清空缓存 */
          chars.length = 0;
          /* 消费掉字符 */
          str = str.slice(1);
        }
        break;
      case STATE.TAG_END:
        if (isAlpha(char)) {
          /* 将当前状态改为 结束标签名称状态 */
          currentState = STATE.TAG_END_NAME;
          /* 将当前字母添加到缓存中 */
          chars.push(char);
          /* 消费掉字符 */
          str = str.slice(1);
        }
        break;
      case STATE.TAG_END_NAME:
        if (isAlpha(char)) {
          /* 将当前字母添加到缓存中 */
          chars.push(char);
          /* 消费掉当前字符 */
          str = str.slice(1);
        } else if (char === ">") {
          /* 将当前状态改为初始状态 */
          currentState = STATE.INITIAL;
          /* 生成一个结束标签 token */
          tokens.push({ type: "tagEnd", name: chars.join("") });
          /* 清空缓存 */
          chars.length = 0;
          /* 消费掉字符 */
          str = str.slice(1);
        }
    }
  }

  /* 返回生成的 Token 序列 */
  return tokens;
}
